﻿using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore;
using B.S.Meeting.Domain;

namespace B.S.Meeting.ReadAPI.Filter
{
    public class AuditTrailInterceptor : SaveChangesInterceptor
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public AuditTrailInterceptor(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        private enum AuditAction
        {
            Create,
            Update,
            Remove
        }

        public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
        {
            HandleAuditFields(eventData);
            return base.SavingChanges(eventData, result);
        }

        public override ValueTask<InterceptionResult<int>> SavingChangesAsync(
            DbContextEventData eventData,
            InterceptionResult<int> result,
            CancellationToken cancellationToken = default)
        {
            HandleAuditFields(eventData);
            return base.SavingChangesAsync(eventData, result, cancellationToken);
        }

        /// <summary>
        /// 统一处理审计字段
        /// </summary>
        /// <param name="eventData"></param>
        private void HandleAuditFields(DbContextEventData eventData)
        {
            if (eventData.Context == null)
                throw new ArgumentNullException(nameof(eventData.Context), "DbContext 不能为空");

            eventData.Context.ChangeTracker.DetectChanges();

            foreach (var entry in eventData.Context.ChangeTracker.Entries())
            {
                if (entry.Entity is not Basedata auditable)
                    continue;

                switch (entry.State)
                {
                    case EntityState.Added:
                        SetAuditFields(auditable, AuditAction.Create);
                        break;
                    case EntityState.Modified:
                        SetAuditFields(auditable, AuditAction.Update);
                        break;
                    case EntityState.Deleted:
                        SetAuditFields(auditable, AuditAction.Remove);
                        entry.State = EntityState.Modified; // 软删除
                        break;
                    case EntityState.Detached:
                    case EntityState.Unchanged:
                        break;
                    default:
                        throw new ArgumentOutOfRangeException(nameof(entry.State), $"未处理的实体状态: {entry.State}");
                }
            }
        }

        /// <summary>
        /// 设置审计字段
        /// </summary>
        private void SetAuditFields(Basedata entity, AuditAction action)
        {
            var now = DateTime.UtcNow;
            var userId = 1;
            var userName = "admin";

            switch (action)
            {
                case AuditAction.Create:
                    entity.CreateTime = now;
                    entity.CreateId = userId;
                    entity.CreateName = userName;
                    break;
                case AuditAction.Update:
                    entity.UpdateTime = now;
                    entity.UpdateId = userId;
                    entity.UpdateName = userName;
                    break;
                case AuditAction.Remove:
                    entity.DelTime = now;
                    entity.DelId = userId;
                    entity.DelName = userName;
                    entity.IsDel = true;
                    break;
                default:
                    throw new ArgumentOutOfRangeException(nameof(action), action, null);
            }
        }
    }
}
